
#include <btPointConstraint.h>

#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BGroupBox>

#include "StringUtils.h"
#include "SixdofConstraintPanel.h"

SixdofConstraintPanel::SixdofConstraintPanel(BWidget* parent) : BWidget(parent)
{
	this->setTitle(BSixdofConstraint::TypeName());

	_bodyAGroupBox = new BGroupBox();
	{
		_pivotAEdit = new BLineEdit();
		_rotateAEdit = new BLineEdit();
		BGridLayout* gridLayout = new BGridLayout(_bodyAGroupBox);
		gridLayout->setWidget(0, 0, new BLabel("pivot"));
		gridLayout->setWidget(0, 1, _pivotAEdit);
		gridLayout->setWidget(1, 0, new BLabel("rotate"));
		gridLayout->setWidget(1, 1, _rotateAEdit);
	}

	_bodyBGroupBox = new BGroupBox();
	{
		_pivotBEdit = new BLineEdit();
		_rotateBEdit = new BLineEdit();
		BGridLayout* gridLayout = new BGridLayout(_bodyBGroupBox);
		gridLayout->setWidget(0, 0, new BLabel("pivot"));
		gridLayout->setWidget(0, 1, _pivotBEdit);
		gridLayout->setWidget(1, 0, new BLabel("rotate"));
		gridLayout->setWidget(1, 1, _rotateBEdit);
	}

	BGroupBox* linearLimitGroupBox = new BGroupBox("Linear Limit");
	{
		BLabel* lowerLabel = new BLabel("lower");
		_linearXMinSpinBox = new BRealSpinBox(-999, 999, 3);
		_linearYMinSpinBox = new BRealSpinBox(-999, 999, 3);
		_linearZMinSpinBox = new BRealSpinBox(-999, 999, 3);

		BLabel* upperLabel = new BLabel("upper");
		_linearXMaxSpinBox = new BRealSpinBox(-999, 999, 3);
		_linearYMaxSpinBox = new BRealSpinBox(-999, 999, 3);
		_linearZMaxSpinBox = new BRealSpinBox(-999, 999, 3);

		BGridLayout* gridLayout = new BGridLayout(linearLimitGroupBox);
		gridLayout->setWidget(1, 0, lowerLabel);
		gridLayout->setWidget(1, 1, _linearXMinSpinBox);
		gridLayout->setWidget(1, 2, _linearYMinSpinBox);
		gridLayout->setWidget(1, 3, _linearZMinSpinBox);
		gridLayout->setWidget(2, 0, upperLabel);
		gridLayout->setWidget(2, 1, _linearXMaxSpinBox);
		gridLayout->setWidget(2, 2, _linearYMaxSpinBox);
		gridLayout->setWidget(2, 3, _linearZMaxSpinBox);
	}

	BGroupBox* angularLimitGroupBox = new BGroupBox("Angular Limit");
	{
		BLabel* lowerLabel = new BLabel("lower");
		_angularXMinSpinBox = new BRealSpinBox(-999, 999, 3);
		_angularYMinSpinBox = new BRealSpinBox(-999, 999, 3);
		_angularZMinSpinBox = new BRealSpinBox(-999, 999, 3);

		BLabel* upperLabel = new BLabel("upper");
		_angularXMaxSpinBox = new BRealSpinBox(-999, 999, 3);
		_angularYMaxSpinBox = new BRealSpinBox(-999, 999, 3);
		_angularZMaxSpinBox = new BRealSpinBox(-999, 999, 3);

		BGridLayout* gridLayout = new BGridLayout(angularLimitGroupBox);
		gridLayout->setWidget(4, 0, lowerLabel);
		gridLayout->setWidget(4, 1, _angularXMinSpinBox);
		gridLayout->setWidget(4, 2, _angularYMinSpinBox);
		gridLayout->setWidget(4, 3, _angularZMinSpinBox);
		gridLayout->setWidget(5, 0, upperLabel);
		gridLayout->setWidget(5, 1, _angularXMaxSpinBox);
		gridLayout->setWidget(5, 2, _angularYMaxSpinBox);
		gridLayout->setWidget(5, 3, _angularZMaxSpinBox);
	}

	_motorGroupBox = new BGroupBox("Motor");
	_motorGroupBox->setCheckable(true);
	_motorGroupBox->setChecked(true);
	{
		BLabel* targetVelocityLabel = new BLabel("Target Velocity");
		_targetVelocitySpinBox = new BRealSpinBox();

		BLabel* maxImpulseLabel = new BLabel("Max Impulse");
		_maxImpulseSpinBox = new BRealSpinBox();

		BGridLayout* gridLayout = new BGridLayout(_motorGroupBox);
		gridLayout->setWidget(2, 0, targetVelocityLabel);
		gridLayout->setWidget(2, 1, _targetVelocitySpinBox);
		gridLayout->setWidget(3, 0, maxImpulseLabel);
		gridLayout->setWidget(3, 1, _maxImpulseSpinBox);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addWidget(_bodyAGroupBox);
	vlayout->addWidget(_bodyBGroupBox);
	vlayout->addWidget(linearLimitGroupBox);
	vlayout->addWidget(angularLimitGroupBox);
	vlayout->addWidget(_motorGroupBox);

	connect(this, Signal_AssetChanged, &SixdofConstraintPanel::slotAssetChanged);

	connect(_pivotAEdit, Signal_EditFinished, &SixdofConstraintPanel::slotPivotAEditFinished);
	connect(_rotateAEdit, Signal_EditFinished, &SixdofConstraintPanel::slotRotateAEditFinished);
	connect(_pivotBEdit, Signal_EditFinished, &SixdofConstraintPanel::slotPivotBEditFinished);
	connect(_rotateBEdit, Signal_EditFinished, &SixdofConstraintPanel::slotRotateBEditFinished);

	connect(_linearXMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearLowerLimitEditFinished);
	connect(_linearYMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearLowerLimitEditFinished);
	connect(_linearZMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearLowerLimitEditFinished);
	connect(_linearXMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearUpperLimitEditFinished);
	connect(_linearYMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearUpperLimitEditFinished);
	connect(_linearZMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotLinearUpperLimitEditFinished);
	connect(_angularXMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularLowerLimitEditFinished);
	connect(_angularYMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularLowerLimitEditFinished);
	connect(_angularZMinSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularLowerLimitEditFinished);
	connect(_angularXMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularUpperLimitEditFinished);
	connect(_angularYMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularUpperLimitEditFinished);
	connect(_angularZMaxSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotAngularUpperLimitEditFinished);
	connect(_motorGroupBox, Signal_Toggled, &SixdofConstraintPanel::slotMotorEnabledToggled);
	connect(_targetVelocitySpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotTargetVelocityEditFinished);
	connect(_maxImpulseSpinBox, Signal_EditFinished, &SixdofConstraintPanel::slotMaxImpulseEditFinished);
}
SixdofConstraintPanel::~SixdofConstraintPanel()
{

}

void SixdofConstraintPanel::slotAssetChanged(BObject* object, const BValue& value)
{
	_sixdofConstraint = value;
	if (_sixdofConstraint)
	{
		if (_sixdofConstraint->nodeA())
		{
			const BVector& pointA = _sixdofConstraint->pointA();
			_bodyAGroupBox->setTitle(_sixdofConstraint->nodeA()->name());
			_pivotAEdit->setText(StringFromVector(pointA));
			//_rotateAEdit->setText(StringFromQuater(matrixA.rotate()));
		}
		if (_sixdofConstraint->nodeB())
		{
			const BVector& pointB = _sixdofConstraint->pointB();
			_bodyBGroupBox->setTitle(_sixdofConstraint->nodeB()->name());
			_pivotBEdit->setText(StringFromVector(pointB));
			//_rotateBEdit->setText(StringFromQuater(matrixB.rotate()));
		}

		const BVector& linearLowerLimit = _sixdofConstraint->linearLowerLimit();
		_linearXMinSpinBox->setValue(linearLowerLimit.x());
		_linearYMinSpinBox->setValue(linearLowerLimit.y());
		_linearZMinSpinBox->setValue(linearLowerLimit.z());
		
		const BVector& linearUpperLimit = _sixdofConstraint->linearUpperLimit();
		_linearXMaxSpinBox->setValue(linearUpperLimit.x());
		_linearYMaxSpinBox->setValue(linearUpperLimit.y());
		_linearZMaxSpinBox->setValue(linearUpperLimit.z());

		const BVector& angleLowerLimit = _sixdofConstraint->angularLowerLimit();
		_angularXMinSpinBox->setValue(angleLowerLimit.x());
		_angularYMinSpinBox->setValue(angleLowerLimit.y());
		_angularZMinSpinBox->setValue(angleLowerLimit.z());

		const BVector& angleUpperLimit = _sixdofConstraint->angularUpperLimit();
		_angularXMaxSpinBox->setValue(angleUpperLimit.x());
		_angularYMaxSpinBox->setValue(angleUpperLimit.y());
		_angularZMaxSpinBox->setValue(angleUpperLimit.z());
	}
}

void SixdofConstraintPanel::slotPivotAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointA = StringToVector(text);
	_sixdofConstraint->setPointA(pointA);
}
void SixdofConstraintPanel::slotRotateAEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BQuater& rotate = StringToQuater(text);
	//BMatrix matrixA = _sixdofConstraint->matrixA();
	//matrixA.setRotate(rotate);
	//_sixdofConstraint->setMatrixA(matrixA);
}
void SixdofConstraintPanel::slotPivotBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BVector& pointB = StringToVector(text);
	_sixdofConstraint->setPointB(pointB);
}
void SixdofConstraintPanel::slotRotateBEditFinished(BObject* object, const BValue& value)
{
	const BString& text = value;
	const BQuater& rotate = StringToQuater(text);
	//BMatrix matrixB = _sixdofConstraint->matrixB();
	//matrixB.setRotate(rotate);
	//_sixdofConstraint->setMatrixB(matrixB);
}

void SixdofConstraintPanel::slotLinearLowerLimitEditFinished(BObject* object, const BValue& value)
{
	BReal minx = _linearXMinSpinBox->value();
	BReal miny = _linearYMinSpinBox->value();
	BReal minz = _linearZMinSpinBox->value();
	_sixdofConstraint->setLinearLowerLimit(minx, miny, minz);
}
void SixdofConstraintPanel::slotLinearUpperLimitEditFinished(BObject* object, const BValue& value)
{
	BReal maxx = _linearXMaxSpinBox->value();
	BReal maxy = _linearYMaxSpinBox->value();
	BReal maxz = _linearZMaxSpinBox->value();
	_sixdofConstraint->setLinearUpperLimit(maxx, maxy, maxz);
}
void SixdofConstraintPanel::slotAngularLowerLimitEditFinished(BObject* object, const BValue& value)
{
	BReal minx = _angularXMinSpinBox->value();
	BReal miny = _angularYMinSpinBox->value();
	BReal minz = _angularZMinSpinBox->value();
	_sixdofConstraint->setAngularLowerLimit(minx, miny, minz);
}
void SixdofConstraintPanel::slotAngularUpperLimitEditFinished(BObject* object, const BValue& value)
{
	BReal maxx = _angularXMaxSpinBox->value();
	BReal maxy = _angularYMaxSpinBox->value();
	BReal maxz = _angularZMaxSpinBox->value();
	_sixdofConstraint->setAngularUpperLimit(maxx, maxy, maxz);
}
void SixdofConstraintPanel::slotMotorEnabledToggled(BObject* object, const BValue& value)
{
	bool motorEnabled = value;

}
void SixdofConstraintPanel::slotTargetVelocityEditFinished(BObject* object, const BValue& value)
{
	BReal targetVelocity = value;

}
void SixdofConstraintPanel::slotMaxImpulseEditFinished(BObject* object, const BValue& value)
{
	BReal maxImpulse = value;

}
